/*
 * ThreadKlasse2.java
 *
 * Created on 6 maart 2008, 19:17
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package racer.client.network.threads;
import java.io.*;
import java.net.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import racer.client.network.*;
import java.util.regex.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

import racer.client.data.RegEx;
import racer.client.data.Setting;



/**
 *
 * @author Lieven
 */
public class IncomingFromServerThread implements Runnable {

	//ipv POS en CHAT en SET miss nummers gebruiken?dan kunnen we dat meteen doorgeven aan case
	//public String positie_expressie = ":=:(.):=:fromID=(.*);X=(.*);Y=(.*);A=(.*);AT=(.*)";
	//public String chat_expressie = ":=:(.):=:fromID=(.*);toID=(.*);text=(.*)";
	//public String settings_expressie = ":=:(.):=:fromID=(.*);toID=(.*);settingstring=(.*)";
	public String positie_expressie;
	public String chat_expressie;
	public String settings_expressie;	
	public String id_expressie;
	//public String expressie="";
	public HashMap<String,String> berichtmap;

	//PositionMessage mess;
	/** Creates a new instance of ThreadKlasse2 */
	NetworkThreadManager ouder;

	public IncomingFromServerThread(NetworkThreadManager t) {
		ouder = t;
		positie_expressie = RegEx.positie_expression;
		chat_expressie = RegEx.chat_expression;
		settings_expressie = RegEx.settings_expression;
		id_expressie = RegEx.id_expression;
		berichtmap = new HashMap<String,String>();
		berichtmap.put("1",positie_expressie);
		berichtmap.put("2",chat_expressie);
		berichtmap.put("3",settings_expressie);
		berichtmap.put("-1","");
	}

	public void run() {
		String responseLine;

		// Keep on reading from the socket till we receive the "Bye" from the server,
		// once we received that then we want to break.
		try {
			while ((responseLine = ouder.is.readLine()) != null) {
				if ((responseLine != null) && (responseLine.length() > 0)){
					//'debug' opzetten (elke lijn dat je binnenkrijgt)
					//System.out.println("server: " + responseLine);                    
					parseMessage(responseLine);
				}
				if (responseLine.indexOf("*** Bye") != -1) break;
			}
			ouder.closed=true;
		} catch (IOException e) {
			System.err.println("IOException:  " + e);
		}
	}

	public void parseMessage(String msg){


		int fromID;
		//messagetype 1 = positie
		//2 = chat
		//3 = setting
		int messageType = messageTypeCheck(msg);
		//Matcher vergelijk = RegEx.getMatcher(berichtmap.get(String.valueOf(messageType)),msg);
		Matcher vergelijk = RegEx.getMatcher(RegEx.getExpression(messageType),msg);
		if(vergelijk == null)
			return;

		if (RegEx.Matches(vergelijk,0)) {
			switch (messageType) {
			case 0:
				System.out.println("login message");
				int playerid = -1;
				try {
					playerid = Integer.parseInt(vergelijk.group(2));
				} catch (NumberFormatException e) {
					e.printStackTrace();
				}
				ouder.setMessageIDs(playerid);
				ouder.getPrefWindow().loggedIn();
				break;
			case 1:  
				try{
					fromID = Integer.parseInt(vergelijk.group(2));         
					double x = Double.parseDouble(vergelijk.group(3));
					double y = Double.parseDouble(vergelijk.group(4));
					int angle = Integer.parseInt(vergelijk.group(5));
					int active_tile_opponent = Integer.parseInt(vergelijk.group(6));

					//this.ouder.getGame().setOpponentPosition(x, y, angle,active_tile_opponent);
					this.ouder.getGame().updateOpponent(fromID, x, y, angle);

					//System.out.println("<"+fromID+"> moves his car to position: (X,Y)=("+x+","+y+") under angle of "+angle+" degrees.");
				}catch(NumberFormatException nu){
					System.err.println("fout"+nu);

				}

				break;
			case 2:
				System.out.println("chat message");
				//toid regelt de server
				//server kan to gedeelte strippen of laten staan(miss goed voor dubbele controle)
				fromID = Integer.parseInt(vergelijk.group(2));                                  
				String textmessage = vergelijk.group(4);
				System.out.println("incoming chat message: <"+fromID+"> says: "+textmessage);

				//bestaat nog niet (om te tonen in gui)
				//this.ouder.getGame().setChatMessage(fromID, textmessage);
				break;

			case 3:
				//settings message
				//bv als speler 1 kleur blauw kiest moet speler 2 dat ook zo tonen
				//of gemeenschappelijke settings die server stuurt !!
				//server uniek id toekennen


				fromID = Integer.parseInt(vergelijk.group(2));                                  
				String settingstext = vergelijk.group(4);
				//speler X houdt zijn settings bij in een gewone hashmap..nog niet als objecten(settingsobject)
				//miss settings object van andere speler koppelen aan zijn entityobject?
				//ook onderscheid maken tss entityobjectsettings en general settings

				Setting receivedSetting = splitSettingsKeyValue(settingstext);
				System.out.println("<"+fromID+"> sets setting: '"+receivedSetting.getsetID()+"' with value: '"+receivedSetting.getsetValue()+"'");                   
				//do something with setting
				//bestaat nog niet
				//this.ouder.getGame().setSetting(receivedSetting);
				break;                   
				//server stuurt altijd lege strings pecies of wel verstuurt client er lege)
			case 4: break;
			case 5: break;
			case 7:
				System.out.println("races list message");
				ArrayList<racer.server.Race> races = new ArrayList<racer.server.Race>();
				String tokenMsg = msg.substring(3, msg.length()-3);
				
				StringTokenizer token = new StringTokenizer(tokenMsg, ";");
				String msgidtoken = token.nextToken();
				String playeridtoken = token.nextToken();
				String raceidtoken = token.nextToken();
				int raceid = -1;
				try {
					String raceidstr = raceidtoken.substring(raceidtoken.indexOf('=')+1);
					raceid = Integer.parseInt(raceidstr);
				} catch (NumberFormatException e) {
					e.printStackTrace();
					return;
				}
				while(raceid != -1) {
					String mapNametoken = token.nextToken();
					String numPlayerstoken = token.nextToken();
					String maxPlayerstoken = token.nextToken();
					String mapName = mapNametoken.substring((mapNametoken.indexOf('=')+1));

					try {
						int numPlayers = Integer.parseInt(numPlayerstoken.substring(numPlayerstoken.indexOf('=')+1));
						int maxPlayers = Integer.parseInt(maxPlayerstoken.substring(maxPlayerstoken.indexOf('=')+1));
						races.add(new racer.server.Race(raceid, mapName, null, numPlayers, maxPlayers));
						
						raceidtoken = token.nextToken();
						String raceidstr = raceidtoken.substring(raceidtoken.indexOf('=')+1);
						raceid = Integer.parseInt(raceidstr);
					} catch (NumberFormatException e) {
						e.printStackTrace();
						return;
					}
				}
				ouder.getPrefWindow().updateRacesList(races);
				
				
				/*
				int i=3;
				String mapName;
				int raceid = -1, numPlayers, maxPlayers;
				//String one = vergelijk.group(1);
				//String two = vergelijk.group(2);
				//String three = vergelijk.group(3);
				try {
					raceid = Integer.parseInt(vergelijk.group(i));
				} catch (NumberFormatException e) { e.printStackTrace();}
				while(raceid >= 0) {
					try {
						mapName = vergelijk.group(i+1);
						numPlayers = Integer.parseInt(vergelijk.group(i+2));
						maxPlayers = Integer.parseInt(vergelijk.group(i+3));
						races.add(new racer.server.Race(raceid, mapName, null, numPlayers, maxPlayers));
						System.out.println("Race: " + raceid + " " + mapName + " " + numPlayers + "/" + maxPlayers);
						i+=4;
						raceid = Integer.parseInt(vergelijk.group(i));
					} catch(NumberFormatException e) {
						e.printStackTrace();
						break;
					}
				}
				*/
				break;
			case 8:
				System.out.println("game over message");
				this.ouder.getGame().setGameOver(true);
				break;
			case 9:
				System.out.println("game started message");
				this.ouder.getGame().setGameStarted(true);
				break;
			case 10:
				System.out.println("map message");
				String mapName = vergelijk.group(2);
				String map = vergelijk.group(3);
				racer.client.data.FileHandlers.saveFileHandler("maps/" + mapName, map);
				ouder.getPrefWindow().startRace();
				break;
			default: System.out.println("No real message,messagetype"+messageType+"\nmessage:"+msg+" msg length: "+msg.length());break;

			}//end switch

		}
	}            



	public int messageTypeCheck(String msg){

		Matcher vergelijk = RegEx.getMatcher(id_expressie,msg);
		if (RegEx.Matches(vergelijk,0)){
			return Integer.parseInt(vergelijk.group(1));
		}else{
			return -1;
		}


	}



	public Setting splitSettingsKeyValue(String settingstext){

		Matcher vergelijk = RegEx.getMatcher("(.*?):(.*)",settingstext);
		if (RegEx.Matches(vergelijk,0)){
			return new Setting(vergelijk.group(1),vergelijk.group(2));
		}else{
			return new Setting("","");
		}


	}    

}
